import { Client, type IMessage, type StompSubscription } from "@stomp/stompjs";
import { Auth } from "@/utils/auth";
import { ref, watch } from "vue";

export interface UseStompOptions {
  brokerURL?: string;
  token?: string;
  reconnectDelay?: number;
  connectionTimeout?: number;
  useExponentialBackoff?: boolean;
  maxReconnectAttempts?: number;
  maxReconnectDelay?: number;
  debug?: boolean;
  url?: string;
}

// 定义订阅存储结构（包含订阅实例、目的地和回调）
interface StoredSubscription {
  subscription: StompSubscription;
  destination: string;
  callback: (_message: IMessage) => void;
}

export function useStomp(options: UseStompOptions = {}) {
  const defaultBrokerURL = import.meta.env.VITE_APP_WS_ENDPOINT || "";
  const brokerURL = ref(options.brokerURL ?? defaultBrokerURL);
  const reconnectDelay = options.reconnectDelay ?? 15000;
  const connectionTimeout = options.connectionTimeout ?? 10000; // 修复ESLint object-shorthand问题
  const useExponentialBackoff = options.useExponentialBackoff ?? false;
  const maxReconnectAttempts = options.maxReconnectAttempts ?? 5;
  const maxReconnectDelay = options.maxReconnectDelay ?? 60000;

  const isConnected = ref(false);
  const reconnectCount = ref(0);
  let reconnectTimer: NodeJS.Timeout | null = null;
  let connectionTimeoutTimer: NodeJS.Timeout | null = null;
  // 修正订阅存储结构，保存目的地信息
  const subscriptions = new Map<string, StoredSubscription>();
  let client: Client | null = null;
  let isConnecting = false;
  let isManualDisconnect = false;

  const getCurrentToken = (): string => {
    return options.token || Auth.getAccessToken() || "";
  };

  const initializeClient = () => {
    if (client) {
      try {
        if (client.active) client.deactivate();
      } catch (error) {
        console.warn("清理旧客户端失败:", error);
      }
      client = null;
    }

    if (!brokerURL.value) {
      console.warn("WebSocket连接失败: 未配置端点URL");
      return false;
    }

    const currentToken = getCurrentToken();
    if (!currentToken) {
      console.warn("WebSocket连接失败：Token为空");
      return false;
    }

    client = new Client({
      brokerURL: brokerURL.value,
      connectHeaders: {
        Authorization: `Bearer ${currentToken}`,
      },
      debug: options.debug ? console.log : () => {},
      reconnectDelay: 0,
      heartbeatIncoming: 4000,
      heartbeatOutgoing: 4000,
      connectionTimeout, // 修复ESLint object-shorthand错误
    });

    client.onConnect = () => {
      isConnected.value = true;
      isConnecting = false;
      reconnectCount.value = 0;
      clearTimeout(connectionTimeoutTimer!);
      console.log("WebSocket连接已建立");
      reSubscribeAfterReconnect();
    };

    client.onDisconnect = () => {
      isConnected.value = false;
      isConnecting = false;
      console.log("WebSocket连接已断开");
      handleReconnect();
    };

    client.onWebSocketClose = (event) => {
      isConnected.value = false;
      isConnecting = false;
      console.log(`WebSocket关闭: ${event.code} ${event.reason}`);

      if (isManualDisconnect) return;

      if ([1000, 1001, 1006, 1008, 1011].includes(event.code)) {
        handleReconnect();
      }
    };

    client.onWebSocketError = (error) => {
      console.error("WebSocket底层错误:", error);
      isConnecting = false;
      handleReconnect();
    };

    client.onStompError = (frame) => {
      console.error("STOMP错误:", frame.headers, frame.body);
      isConnecting = false;

      if (frame.headers.message?.includes("Token") || frame.body?.includes("Token")) {
        console.warn("Token无效，尝试刷新Token并重连");
        if (Auth.refreshAccessToken) {
          Auth.refreshAccessToken()
            .then(() => {
              console.log("Token刷新成功，开始重连");
              handleReconnect();
            })
            .catch((error) => {
              console.error("Token刷新失败:", error);
              isManualDisconnect = true;
            });
        } else {
          isManualDisconnect = true;
        }
      }
    };

    return true;
  };

  // 修复重连后订阅恢复逻辑
  const reSubscribeAfterReconnect = () => {
    if (subscriptions.size === 0 || !client?.connected) return;

    const tempSubscriptions = Array.from(subscriptions.entries());
    subscriptions.clear();

    tempSubscriptions.forEach(([id, storedSub]) => {
      const newSub = client!.subscribe(storedSub.destination, storedSub.callback);
      subscriptions.set(id, {
        subscription: newSub,
        destination: storedSub.destination,
        callback: storedSub.callback,
      });
    });
    console.log(`重连后恢复${subscriptions.size}个订阅`);
  };

  const handleReconnect = () => {
    if (isManualDisconnect || reconnectCount.value >= maxReconnectAttempts) return;

    reconnectCount.value++;
    console.log(`准备重连(${reconnectCount.value}/${maxReconnectAttempts})...`);

    const delay = useExponentialBackoff
      ? Math.min(reconnectDelay * Math.pow(2, reconnectCount.value - 1), maxReconnectDelay)
      : reconnectDelay;

    if (reconnectTimer) clearTimeout(reconnectTimer);
    reconnectTimer = setTimeout(() => {
      if (!isConnected.value && !isManualDisconnect) {
        console.log("开始重连...");
        connect();
      }
    }, delay);
  };

  watch(brokerURL, (newURL) => {
    if (newURL && client?.connected) {
      disconnect();
      connect();
    }
  });

  const connect = () => {
    isManualDisconnect = false;
    if (isConnecting || isConnected.value) return;

    isConnecting = true;
    console.log("正在建立WebSocket连接...");

    const initSuccess = initializeClient();
    if (!initSuccess) {
      isConnecting = false;
      handleReconnect();
      return;
    }

    clearTimeout(connectionTimeoutTimer!);
    connectionTimeoutTimer = setTimeout(() => {
      if (!isConnected.value && isConnecting) {
        console.warn("WebSocket连接超时");
        isConnecting = false;
        client?.deactivate();
        handleReconnect();
      }
    }, connectionTimeout);

    try {
      client!.activate();
    } catch (error) {
      console.error("连接激活失败:", error);
      isConnecting = false;
      handleReconnect();
    }
  };

  // 修复订阅方法的存储结构
  const subscribe = (destination: string, callback: (_message: IMessage) => void): string => {
    if (!client?.connected) {
      console.warn(`订阅失败: 未连接，暂存订阅(${destination})`);
      const tempId = `temp-${Date.now()}`;
      subscriptions.set(tempId, {
        subscription: null as unknown as StompSubscription,
        destination,
        callback,
      });
      return tempId;
    }

    const subscription = client.subscribe(destination, callback);
    const subId = subscription.id;
    subscriptions.set(subId, {
      subscription,
      destination,
      callback,
    });
    console.log(`订阅成功: ${destination}`);
    return subId;
  };

  const disconnect = () => {
    isManualDisconnect = true;
    clearTimeout(reconnectTimer!);
    clearTimeout(connectionTimeoutTimer!);
    subscriptions.clear();
    if (client?.active) client.deactivate();
    client = null;

    isConnected.value = false;
    isConnecting = false;
    reconnectCount.value = 0;
    console.log("手动断开连接");
  };

  return {
    isConnected,
    connect,
    subscribe,
    unsubscribe: (id: string) => subscriptions.delete(id),
    disconnect,
  };
}
